package ua.kpi.ipsa.expert.api.db;

import java.util.Comparator;

import com.sleepycat.bind.tuple.IntegerBinding;
import com.sleepycat.bind.tuple.LongBinding;
import com.sleepycat.bind.tuple.TupleInput;
import com.sleepycat.bind.tuple.TupleOutput;
import com.sleepycat.je.DatabaseEntry;
import com.sleepycat.je.SecondaryDatabase;
import com.sleepycat.je.SecondaryKeyCreator;

public class CodePortionTuple implements Cloneable {

	public int codePortionPK;
	public String userLogin = null;
	public String studentName = null;
	public String group = null;
	public String vooz = null;
	public String etc = null;

	public long time;

	public CodePortionTuple() {
	}

	public CodePortionTuple(int codePortionPK) {
		this.codePortionPK = codePortionPK;
	}

	CodePortionTuple(DatabaseEntry key, DatabaseEntry data) {
		setKeyEntry(key);
		setValueEntry(data);
	}

	DatabaseEntry getKeyEntry() {
		DatabaseEntry entry = new DatabaseEntry();
		IntegerBinding.intToEntry(codePortionPK, entry);
		return entry;
	}

	@Override
	public CodePortionTuple clone() {
		CodePortionTuple c = null;
		try {
			c = (CodePortionTuple) super.clone();
		} catch (CloneNotSupportedException e) {
		}
		return c;
	}

	void setKeyEntry(DatabaseEntry entry) {
		codePortionPK = IntegerBinding.entryToInt(entry);
	}

	DatabaseEntry getValueEntry() {
		DatabaseEntry entry = new DatabaseEntry();
		TupleOutput out = new TupleOutput();
		out.writeString(userLogin);
		out.writeString(studentName);
		out.writeString(group);
		out.writeString(vooz);
		out.writeString(etc);
		out.writeLong(time);
		entry.setData(out.getBufferBytes(), out.getBufferOffset(),
				out.getBufferLength());
		return entry;
	}

	void setValueEntry(DatabaseEntry entry) {
		TupleInput in = new TupleInput(entry.getData(), entry.getOffset(),
				entry.getSize());
		userLogin = in.readString();
		studentName = in.readString();
		group = in.readString();
		vooz = in.readString();
		etc = in.readString();
		time = in.readLong();
	}

	static final SecondaryKeyCreator TIME_CREATOR = new SecondaryKeyCreator() {

		@Override
		public boolean createSecondaryKey(SecondaryDatabase secondary,
				DatabaseEntry key, DatabaseEntry data, DatabaseEntry result) {
			LongBinding.longToEntry(new CodePortionTuple(key, data).time,
					result);
			return true;
		}
	};

	static final SecondaryKeyCreator USER_LOGIN_CREATOR = new SecondaryKeyCreator() {

		@Override
		public boolean createSecondaryKey(SecondaryDatabase secondary,
				DatabaseEntry key, DatabaseEntry data, DatabaseEntry result) {
			TupleOutput out = new TupleOutput();
			CodePortionTuple c = new CodePortionTuple(key, data);
			out.writeString(c.userLogin);
			out.writeLong(c.time);
			result.setData(out.getBufferBytes(), out.getBufferOffset(),
					out.getBufferLength());
			return true;
		}
	};

	static final SecondaryKeyCreator STUDENT_NAME_CREATOR = new SecondaryKeyCreator() {

		@Override
		public boolean createSecondaryKey(SecondaryDatabase secondary,
				DatabaseEntry key, DatabaseEntry data, DatabaseEntry result) {
			TupleOutput out = new TupleOutput();
			CodePortionTuple c = new CodePortionTuple(key, data);
			out.writeString(c.studentName);
			out.writeLong(c.time);
			result.setData(out.getBufferBytes(), out.getBufferOffset(),
					out.getBufferLength());
			return true;
		}
	};

	static final SecondaryKeyCreator GROUP_CREATOR = new SecondaryKeyCreator() {

		@Override
		public boolean createSecondaryKey(SecondaryDatabase secondary,
				DatabaseEntry key, DatabaseEntry data, DatabaseEntry result) {
			TupleOutput out = new TupleOutput();
			CodePortionTuple c = new CodePortionTuple(key, data);
			out.writeString(c.vooz);
			out.writeString(c.group);
			out.writeLong(c.time);
			result.setData(out.getBufferBytes(), out.getBufferOffset(),
					out.getBufferLength());
			return true;
		}
	};

	static final SecondaryKeyCreator VOOZ_CREATOR = new SecondaryKeyCreator() {

		@Override
		public boolean createSecondaryKey(SecondaryDatabase secondary,
				DatabaseEntry key, DatabaseEntry data, DatabaseEntry result) {
			TupleOutput out = new TupleOutput();
			CodePortionTuple c = new CodePortionTuple(key, data);
			out.writeString(c.vooz);
			out.writeLong(c.time);
			result.setData(out.getBufferBytes(), out.getBufferOffset(),
					out.getBufferLength());
			return true;
		}
	};

	static final Comparator<byte[]> STRING_LONG_COMPARATOR = new DBComparator() {

		private static final long serialVersionUID = -2429200434767945019L;

		@Override
		public int compare(byte[] b1, byte[] b2) {
			TupleInput in1 = new TupleInput(b1);
			TupleInput in2 = new TupleInput(b2);
			int c = in1.readString().compareTo(in2.readString());
			if (c != 0)
				return c;
			long l1 = in1.readLong();
			long l2 = in2.readLong();
			return l1 < l2 ? -1 : l1 == l2 ? 0 : 1;
		}
	};

	static final Comparator<byte[]> STRING_STRING_LONG_COMPARATOR = new DBComparator() {

		private static final long serialVersionUID = -4154305195766912859L;

		@Override
		public int compare(byte[] b1, byte[] b2) {
			TupleInput in1 = new TupleInput(b1);
			TupleInput in2 = new TupleInput(b2);
			int c = in1.readString().compareTo(in2.readString());
			if (c != 0)
				return c;
			c = in1.readString().compareTo(in2.readString());
			if (c != 0)
				return c;
			long l1 = in1.readLong();
			long l2 = in2.readLong();
			return l1 < l2 ? -1 : l1 == l2 ? 0 : 1;
		}
	};
}
